/*
 * Copyright (c) 2023-2024 elsfs Authors. All Rights Reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.elsfs.cloud.screw;

import java.io.Serializable;
import javax.sql.DataSource;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.ToString;
import org.elsfs.cloud.common.util.lang.Assert;
import org.elsfs.cloud.screw.engine.EngineConfig;
import org.elsfs.cloud.screw.process.ProcessConfig;

/**
 * Screw 配置入口
 *
 * @author zeng
 */
@Data
@NoArgsConstructor
public class Configuration implements Serializable {

  /** 组织 */
  private String organization;

  /** url */
  private String organizationUrl;

  /** 标题 */
  private String title;

  /** 版本号 */
  private String version;

  /** 描述 */
  private String description;

  /** 数据源，这里直接使用@see{@link DataSource}接口，好处就，可以使用任何数据源 */
  private DataSource dataSource;

  /** 生成配置 */
  private ProcessConfig produceConfig;

  /** 引擎配置，关于数据库文档生成相关配置 */
  private EngineConfig engineConfig;

  /**
   * 构造函数
   *
   * @param title {@link String} 标题
   * @param organization {@link String} 机构
   * @param version {@link String} 版本
   * @param description {@link String} 描述
   * @param dataSource {@link DataSource} 数据源
   * @param produceConfig {@link ProcessConfig} 生成配置
   * @param engineConfig {@link EngineConfig} 生成配置
   */
  private Configuration(
      String organization,
      String organizationUrl,
      String title,
      String version,
      String description,
      DataSource dataSource,
      ProcessConfig produceConfig,
      EngineConfig engineConfig) {
    Assert.notNull(dataSource, "DataSource can not be empty!");
    Assert.notNull(engineConfig, "EngineConfig can not be empty!");
    this.title = title;
    this.organizationUrl = organizationUrl;
    this.organization = organization;
    this.version = version;
    this.description = description;
    this.dataSource = dataSource;
    this.engineConfig = engineConfig;
    this.produceConfig = produceConfig;
  }

  /**
   * builder
   *
   * @return {@link Configuration.ConfigurationBuilder}
   */
  public static Configuration.ConfigurationBuilder builder() {
    return new Configuration.ConfigurationBuilder();
  }

  /** builder */
  @ToString
  public static class ConfigurationBuilder {
    private String organization;
    private String organizationUrl;
    private String title;
    private String version;
    private String description;
    private DataSource dataSource;
    private ProcessConfig produceConfig;
    private EngineConfig engineConfig;

    public Configuration.ConfigurationBuilder organization(String org) {
      this.organization = org;
      return this;
    }

    public Configuration.ConfigurationBuilder organizationUrl(String orgUrl) {
      this.organizationUrl = orgUrl;
      return this;
    }

    public Configuration.ConfigurationBuilder title(String title) {
      this.title = title;
      return this;
    }

    public Configuration.ConfigurationBuilder version(String version) {
      this.version = version;
      return this;
    }

    public Configuration.ConfigurationBuilder description(String description) {
      this.description = description;
      return this;
    }

    public Configuration.ConfigurationBuilder dataSource(DataSource dataSource) {
      this.dataSource = dataSource;
      return this;
    }

    public Configuration.ConfigurationBuilder produceConfig(ProcessConfig processConfig) {
      this.produceConfig = processConfig;
      return this;
    }

    public Configuration.ConfigurationBuilder engineConfig(EngineConfig engineConfig) {
      this.engineConfig = engineConfig;
      return this;
    }

    /**
     * build
     *
     * @return {@link Configuration}
     */
    public Configuration build() {
      return new Configuration(
          this.organization,
          this.organizationUrl,
          this.title,
          this.version,
          this.description,
          this.dataSource,
          this.produceConfig,
          this.engineConfig);
    }
  }
}
